
#ifndef _IWRITER_H_
#define _IWRITER_H_

#include <BMap>
#include <BStream>
#include <BImage>
#include <BImage>
#include <BFont>
#include <BNode>
#include <BLight>
#include <BCamera>
#include <BScene>
#include <BDisplay>
#include <BMesh>
#include <BShape>
#include <BGeometry>
#include <BMaterial>
#include <BTexture>
#include <BProgram>
#include <BCone>
#include <BCube>
#include <BCylinder>
#include <BSphere>
#include <BTorus>
#include <BMesh>
#include <BSurface>
#include <BWidget>
#include <BLayout>
#include <BButton>
#include <BSlider>
#include <BScrollArea>
#include <BComboBox>
#include <BCheckBox>
#include <BSpinBox>
#include <BLineEdit>
#include <BTextEdit>
#include <BTreeWidget>
#include <BListWidget>
#include <BTableWidget>
#include <BScrollBar>
#include <BScrollWidget>
#include <BLabel>
#include <BMenu>
#include <BMenuBar>
#include <BDialog>
#include <BGroupBox>
#include <BSplitter>
#include <BTabWidget>
#include <BViewer>
#include "IBlockSign.h"

#include <BReadWrite>

namespace BWE
{
	class IWriter
	{
	public:
		IWriter();
		~IWriter();

		bool writeObject(const BObject* object, const BString& fileName);

	private://write
		template<class T>
		bool write(int sign, const T& value)
		{
			Block block;
			block.sign = sign;
			block.begin = stream->offset();
			if (!stream->wmove(sizeof(Block)))
			{
				puts("wmove faild.");
				return false;
			}
			if (!stream->write(value))
			{
				puts("write faild.");
				return false;
			}
			block.end = stream->offset();
			block.size = block.end - block.begin - sizeof(Block);
			stream->seek(block.begin);
			stream->write(block);
			stream->seek(block.end);
			return true;
		}

		bool write(const BObject* object);
		bool write(int sign, const BObject* object);

		bool writeObjectData(const BObject* object);
		bool writeNodeData(const BNode* node);
		bool writeShapeData(const BShape* shape);
		bool writeMeshData(const BMesh* mesh);
		bool writeTextureData(const BTexture* texture);
		bool writeWidgetData(const BWidget* widget);

		bool writeNode(const BNode* node);
		bool writeLight(const BLight* light);
		bool writeCamera(const BCamera* camera);
		bool writeScene(const BScene* scene);

		bool writeShape(const BShape* shape);
		bool writeMesh(const BMesh* mesh);
		bool writeGeometry(const BGeometry* geometry);
		bool writeCone(const BCone* cone);
		bool writeCube(const BCube* cube);
		bool writeCylinder(const BCylinder* cylinder);
		bool writeSphere(const BSphere* sphere);
		bool writeTorus(const BTorus* torus);
		bool writeSurface(const BSurface* surface);

		bool writeState(const BState* state);
		bool writeMaterial(const BMaterial* material);
		bool writeTexture(const BTexture* texture);
		bool writeProgram(const BProgram* program);
		bool writeImage(const BImage* image);

		bool writeWidget(const BWidget* widget);
		bool writePalette(const BStyle* style);
		bool writeCursor(const BCursor* cursor);
		bool writeFont(const BFont* font);

		bool writeButton(const BButton* button);
		bool writeSlider(const BSlider* slider);
		bool writeScrollArea(const BScrollArea* scrollArea);
		bool writeComboBox(const BComboBox* comboBox);
		bool writeCheckBox(const BCheckBox* checkBox);
		bool writeSpinBox(const BSpinBox* spinBox);
		bool writeLineEdit(const BLineEdit* lineEdit);
		bool writeTextEdit(const BTextEdit* textEidt);
		bool writeTreeWidget(const BTreeWidget* treeWidget);
		bool writeListWidget(const BListWidget* listWidget);
		bool writeTableWidget(const BTableWidget* tableWidget);
		bool writeScrollBar(const BScrollBar* scrollBar);
		bool writeScrollWidget(const BScrollWidget* scrollWidget);
		bool writeLabel(const BLabel* label);
		bool writeMenu(const BMenu* menu);
		bool writeMenuBar(const BMenuBar* menuBar);
		bool writeDialog(const BDialog* dialog);
		bool writeGroupBox(const BGroupBox* groupBox);
		bool writeSplitter(const BSplitter* splitter);
		bool writeTabWidget(const BTabWidget* tabWidget);
		bool writeViewer(const BViewer* viewer);

	private:
		void print();
		void print(const char* cstr);
		void print(const BString& str);

	private:
		typedef bool(IWriter::*Write)(const BObject* object);
		BMap<int, Write>		writeMap;

		BMap<int, BString>		textMap;
		BMap<BString, int>		signMap;

		BStream*		stream;
		Block			block;
		BList<Block>	stack;
	};
}

#endif